package model

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/Unknwon/com"
	"github.com/levigross/grequests"
	"github.com/tidwall/gjson"

	"gitee.com/goframe/lt-collector/libs/libce"
	"gitee.com/goframe/lt-collector/libs/orma"
	"gitee.com/goframe/lt-collector/libs/utils"
)

func (m *GameCollectSource) trimSpace() {
	strings.TrimSpace(m.Name)
	strings.TrimSpace(m.SourceURL)
}

type (
	//SourceParam ...
	SourceParam interface {
		getByGid(gid int64) error
		//GetParam get request param
		GetParam() (paramString string, err error)
		//GetData 获取接口数据
		GetData(apiURL string) (data RequestData, err error)
	}

	//RequestData 采集数据接口
	RequestData interface {
		GetOpenIssue() string
		GetOpenCode() string
		GetOpenTime() orma.JSONTime
	}
)

//KcwData 开采网数据
type KcwData struct {
	Expect        string         `json:"expect"`
	OpenCode      string         `json:"opencode"`
	OpenTime      *orma.JSONTime `json:"opentime"`
	OpenTimestamp int64          `json:"opentimestamp"`
}

func (k *KcwData) GetOpenIssue() string {
	return strings.Replace(k.Expect, "-", "", -1)
}

func (k *KcwData) GetOpenCode() string {
	return k.OpenCode
}

func (k *KcwData) GetOpenTime() orma.JSONTime {
	return *k.OpenTime
}

//Data168kai 168kai开奖数据
type Data168kai struct {
	Issue    interface{}    `json:"preDrawIssue"`
	OpenCode string         `json:"preDrawCode"`
	OpenTime *orma.JSONTime `json:"preDrawTime"`
}

func (k *Data168kai) GetOpenIssue() string {
	return strings.Replace(com.ToStr(k.Issue), "-", "", -1)
}

func (k *Data168kai) GetOpenCode() string {
	return k.OpenCode
}

func (k *Data168kai) GetOpenTime() orma.JSONTime {
	return *k.OpenTime
}

//GetData 获取168kai接口数据
func (m *GameSourceParam168) GetData(apiURL string) (data RequestData, err error) {
	rq := utils.NewRequester()
	rq.SetOption(&grequests.RequestOptions{
		UserAgent:   utils.UserAgent,
		DialTimeout: time.Second * 2,
	})
	rq.SetUrl(apiURL)
	rq.SetRequestFunc(func(rp *grequests.Response) (e error) {
		bts := rp.Bytes()
		if !gjson.ValidBytes(bts) {
			return fmt.Errorf("%s", bts)
		}
		rst := gjson.ParseBytes(bts)
		if rst.Get("errCode").Int() != 0 {
			return errors.New(rst.Get("message").String())
		}
		dataRst := rst.Get("result.data")
		if !dataRst.Exists() {
			return fmt.Errorf("%s", bts)
		}
		data = new(Data168kai)
		e = json.UnmarshalFromString(dataRst.String(), data)
		return
	})
	err = rq.Request(utils.GET)
	return
}

//GetData 获取开采网接口数据
func (m *GameSourceParamKcw) GetData(apiURL string) (data RequestData, err error) {
	rq := utils.NewRequester()
	rq.SetOption(&grequests.RequestOptions{
		UserAgent:   utils.UserAgent,
		DialTimeout: time.Second * 2,
	})
	rq.SetUrl(apiURL)
	rq.SetRequestFunc(func(rp *grequests.Response) (e error) {
		bts := rp.Bytes()
		if !gjson.ValidBytes(bts) {
			return fmt.Errorf("%s", bts)
		}
		rst := gjson.ParseBytes(bts)
		dataRst := rst.Get("data")
		if !dataRst.Exists() {
			return fmt.Errorf("%s", bts)
		}
		dataSlice := dataRst.Array()
		if len(dataSlice) == 0 {
			return fmt.Errorf("%s", dataRst.String())
		}
		data = new(KcwData)
		e = json.UnmarshalFromString(dataSlice[0].String(), data)
		return
	})
	err = rq.Request(utils.GET)
	return
}

func (m *GameSourceParamKcw) GetParam() (paramString string, err error) {
	//get token
	st := new(SysSetting)
	if err = st.GetByKey("KCW_Token"); err != nil {
		return
	}
	paramString = fmt.Sprintf("?rows=1&format=json&token=%s&code=%s", st.Value, m.Code)
	return
}

func (m *GameSourceParam168) GetParam() (paramString string, err error) {
	paramString = fmt.Sprintf("?lotCode=%s", m.LotCode)
	return
}

func (m *GameSourceParam168) getByGid(gid int64) error {
	return libce.CacheBindModelByKey(m, fmt.Sprintf("gid:%d", gid), func() error {
		err := orma.NormalGet(m.Session().Where("gid=?", gid).Get(m))
		if err == orma.ErrOrmNotFound {
			err = fmt.Errorf("采集错误:Gid:[%d]未设置采集点参数", gid)
		}
		return err
	})
}

func (m *GameSourceParamKcw) getByGid(gid int64) error {
	return libce.CacheBindModelByKey(m, fmt.Sprintf("gid:%d", gid), func() error {
		err := orma.NormalGet(m.Session().Where("gid=?", gid).Get(m))
		if err == orma.ErrOrmNotFound {
			err = fmt.Errorf("采集错误:Gid:[%d]未设置采集点参数", gid)
		}
		return err
	})
}

func (m *GameCollectSource) getRequestData(gid int64) (data RequestData, err error) {
	defer func() {
		if err != nil {
			err = checkErr(err, "getRequestData")
		}
	}()
	if err = BindIDModel(m); err != nil {
		return
	}
	var (
		paramBean SourceParam
		has       bool
	)
	collectors := map[int]SourceParam{
		SCKcw: new(GameSourceParamKcw),
		SC168: new(GameSourceParam168),
		SCBy:  new(ByCollector),
		SCTx:  new(TXCollector),
	}
	if paramBean, has = collectors[m.SourceType]; !has {
		err = errors.New("未知的采集站点")
		return
	}
	if err = paramBean.getByGid(gid); err != nil {
		return
	}
	var paramString string
	paramString, err = paramBean.GetParam()
	if err != nil {
		return
	}
	apiURI := fmt.Sprintf("%s%s", m.SourceURL, paramString)
	data, err = paramBean.GetData(apiURI)
	return
}
